package cn.wolfcode.interceptor;

import cn.wolfcode.annotation.BrushProof;
import cn.wolfcode.redis.service.ISecurityRedisService;
import cn.wolfcode.redis.util.RedisKeys;
import cn.wolfcode.util.IPConvert;
import cn.wolfcode.util.IPUtil;
import cn.wolfcode.util.JSONResult;
import cn.wolfcode.util.RequestUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

@Component
public class BrushProofInterceptor implements HandlerInterceptor {

    @Autowired
    ISecurityRedisService securityRedisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI().substring(1);
        // ip最好转换成数字，这个现在是一堆冒号
        String ip = String.valueOf(RequestUtil.getIPAddress().replace(":", "."));
        String key = RedisKeys.BRUSH_PROOF.join(uri, ip);
        // 防刷
        boolean allowBrush = true;
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            boolean has = handlerMethod.hasMethodAnnotation(BrushProof.class);
            if (uri.contains("/regist")) {
                // 注册接口特殊处理
                boolean allowBrushReg = securityRedisService.isAllowBrushReg(key);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(JSON.toJSONString(JSONResult.error(503, "访问过于频繁，请稍后再注册", "访问过于频繁")));
                return false;
            } else if (!has) {
                // 没有特殊标记的使用默认配置
                allowBrush = securityRedisService.isAllowBrush(key);

            } else {
                // 单独设置的读取注解
                BrushProof brushProof = handlerMethod.getMethodAnnotation(BrushProof.class);
                int time = brushProof.time();
                int count = brushProof.count();
                TimeUnit unit = brushProof.timeUnit();
                allowBrush = securityRedisService.isAllowBrush(time, count, unit, key);
            }
        }


        // 如果不允许访问，提示用户并记一次违规
        if (!allowBrush) {
            securityRedisService.addIllegalCount(ip);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(JSONResult.error(503, "访问过于频繁，此IP已被封禁24小时", "访问过于频繁，此IP已被封禁24小时")));
            return false;
        }

        return true;
    }
}
